package com.sky.service.admin.impl;

import com.sky.mapper.user.OrderMapper;
import com.sky.mapper.user.UserMapper;
import com.sky.pojo.Orders;
import com.sky.service.admin.ReportService;
import com.sky.vo.OrderReportVO;
import com.sky.vo.SalesTop10ReportVO;
import com.sky.vo.TurnoverReportVO;
import com.sky.vo.UserReportVO;
import net.bytebuddy.dynamic.NexusAccessor;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.aspectj.runtime.internal.cflowstack.ThreadCounterImpl11;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sun.security.jca.GetInstance;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.soap.SOAPHeaderElement;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Description ReportServiceImpl
 * @Author lyh
 * @Date 2024-11-06
 */
@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;

    /*@Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        List<String> dateList=new ArrayList<>();
        while(!begin.isAfter(end)){
           dateList.add(begin.toString());
           begin=begin.plusDays(1);
        }
       List<Double> totalList=new ArrayList<>();
        for (String date : dateList) {
            Double total= orderMapper.countDayReport(date);
            if(total==null){
                total=0.0;
            }
            totalList.add(total);
        }
        String dateListStr=StringUtils.join(dateList,",");
        String total = StringUtils.join(totalList, ",");
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        turnoverReportVO.setDateList(dateListStr);
        turnoverReportVO.setTurnoverList(total);
        return turnoverReportVO;
    }*/
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        String beginString = begin.toString();
        String endString = end.toString();
        List<String> dateList = new ArrayList<>();
        while (!begin.isAfter(end)) {
            dateList.add(begin.toString());
            begin = begin.plusDays(1);
        }
        Map<String, BigDecimal> map = orderMapper.countReport(beginString, endString, dateList);
        List<Double> totalList = new ArrayList<>();
        /*
        //数据位置可能不对应
        for(Map.Entry<String,BigDecimal> entry: map.entrySet()){
            BigDecimal value = entry.getValue();
            totalList.add(value.doubleValue());
        }*/
        for (String date : dateList) {
            BigDecimal value = map.get(date);
            totalList.add(value.doubleValue());
        }
        String dateListStr = StringUtils.join(dateList, ",");
        String total = StringUtils.join(totalList, ",");
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        turnoverReportVO.setDateList(dateListStr);
        turnoverReportVO.setTurnoverList(total);
        return turnoverReportVO;
    }

    /**
     * 订单统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        String beginString = begin.toString();
        String endString = end.toString();
        List<String> dateList = new ArrayList<>();
        while (!begin.isAfter(end)) {
            dateList.add(begin.toString());
            begin = begin.plusDays(1);
        }
        Future<?> future = threadPoolExecutor.submit(() -> {
            //统计给的时间段的订单总量
            return orderMapper.selectTotalOrderByDateAndStatus(beginString, endString, null);
        });
        Future<?> future2 = threadPoolExecutor.submit(() -> {
            //统计给的时间段的有效订单量
            return orderMapper.selectTotalOrderByDateAndStatus(beginString, endString, Orders.COMPLETE_ORDER);
        });
        Future<?> future3 = threadPoolExecutor.submit(() -> {
            //统计这段时间每天的订单总量
            return orderMapper.selectDayTotalOrderByDateAndStatus(dateList, beginString, endString, null);
        });
        Future<?> future4 = threadPoolExecutor.submit(() -> {
            //统计这段时间每天的有效订单总量
            return orderMapper.selectDayTotalOrderByDateAndStatus(dateList, beginString, endString, Orders.COMPLETE_ORDER);
        });
        Map<String, Long> map1 = new HashMap<>();
        Long count = 0L;
        Long count2 = 0L;
        Map<String, Long> map2 = new HashMap<>();
        try {
            count = (Long) future.get();
            count2 = (Long) future2.get();
            map2 = (Map<String, Long>) future4.get();
            map1 = (Map<String, Long>) future3.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<Long> orderCountList = new ArrayList<>();
        List<Long> validOrderCountList = new ArrayList<>();
        for (String date : dateList) {
            Long value1 = map1.get(date);
            Long value2 = map2.get(date);
            orderCountList.add(value1);
            validOrderCountList.add(value2);
        }
        double orderCompletionRate = count2 * 1.0 / count;
        OrderReportVO reportVO = OrderReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .totalOrderCount(count.intValue())
                .validOrderCount(count2.intValue())
                .orderCompletionRate(orderCompletionRate)
                .orderCountList(StringUtils.join(orderCountList, ","))
                .validOrderCountList(StringUtils.join(validOrderCountList, ","))
                .build();

        return reportVO;
    }

    /**
     * 用户数量统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        String beginStr = begin.toString();
        String endStr = end.toString();
        List<String> dateList = new ArrayList<>();
        while (!begin.isAfter(end)) {
            dateList.add(begin.toString());
            begin = begin.plusDays(1);
        }
        //查询起始时间之前的所有用户数量total
        Long total = userMapper.selectCountBeforeDate(beginStr);
        //统计给的时间段每天新增的用户量
        Map<String, Long> map = userMapper.selectCountEveryDateUser(dateList, beginStr, endStr);
        //根据dateList遍历，当天的用户量=total+新增
        List<Long> totalUserList = new ArrayList<>();
        List<Long> newUserList = new ArrayList<>();
        for (String date : dateList) {
            Long newUser = map.get(date);
            total = total + newUser;
            totalUserList.add(total);
            newUserList.add(newUser);
        }
        UserReportVO reportVO = UserReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .totalUserList(StringUtils.join(totalUserList, ","))
                .newUserList(StringUtils.join(newUserList, ","))
                .build();
        return reportVO;
    }

    /**
     * 销量排名top10
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        String beginString = begin.toString();
        String endString = end.toString();
        List<Map<String, Object>> list = orderMapper.selectTop10(beginString, endString);
        List<String> nameList = new ArrayList<>();
        List<String> numberList = new ArrayList<>();
        for (Map<String, Object> map : list) {
            String name = map.get("name").toString();
            nameList.add(name);
            String num = map.get("num").toString();
            numberList.add(num);
        }
        SalesTop10ReportVO reportVO = SalesTop10ReportVO.builder()
                .nameList(StringUtils.join(nameList, ","))
                .numberList(StringUtils.join(numberList, ","))
                .build();
        return reportVO;
    }

    /**
     * 导出运营数据报表
     *
     * @param response
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) {
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("static/运营数据报表模板.xlsx");
        XSSFWorkbook excel = null;
        try {
            excel = new XSSFWorkbook(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        XSSFSheet sheet = excel.getSheet("sheet1");
        XSSFRow row1 = sheet.getRow(3);
        row1.getCell(2).setCellValue(1500);
        row1.getCell(4).setCellValue("80%");
        row1.getCell(6).setCellValue(200);
        XSSFRow row2 = sheet.getRow(4);
        row2.getCell(2).setCellValue(30);
        row2.getCell(4).setCellValue(50);
        Calendar instance = Calendar.getInstance();
        int maximum = instance.getActualMaximum(Calendar.DAY_OF_MONTH);
        int minimum = instance.getActualMinimum(Calendar.DAY_OF_MONTH);
        //设置日历中月份的最小天数
        instance.set(Calendar.DAY_OF_MONTH,minimum);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String frist = sdf.format(instance.getTime());
        //设置日历中月份的最大天数
        instance.set(Calendar.DAY_OF_MONTH,maximum);
        String lastDay = sdf.format(instance.getTime());
        LocalDate begin = LocalDate.parse(frist);
        LocalDate end = LocalDate.parse(lastDay);
        int num=7;
        while(!begin.isAfter(end)){
            XSSFRow row = sheet.getRow(num);
            row.getCell(1).setCellValue(begin.toString());
            row.getCell(2).setCellValue(1500);
            row.getCell(3).setCellValue(30);
            row.getCell(4).setCellValue("80%");
            row.getCell(5).setCellValue(50);
            row.getCell(6).setCellValue(200);
            num++;
            begin=begin.plusDays(1);
        }
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            excel.write(outputStream);
            outputStream.close();
            excel.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
